package cn.daomeng.firebird.mq.rabbit;

import java.util.Collection;
import java.util.Iterator;

import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 自动注入rabbtiMq相关对象
 * @author Qin.Siliang
 * @since 2019/3/5
 */
@Configuration
public class RabbitMQAutoConfiguration implements ApplicationContextAware{

    private ApplicationContext applicationContext;

    private RabbitMQService rabbitMQService;

    /** 是否启用rabbitMq的自动注册*/
    @Value("${calorie.rabbitmq.enter:false}")
    private boolean enter;

    /** 是否启用rabbitMq的自动注册*/
    @Value("${calorie.rabbitmq.isAli:false}")
    private boolean isAli;

    /** 是否启用rabbitMq的自动注册*/
    @Value("${calorie.rabbitmq.autoListen:false}")
    private boolean autoListen;

    /** 服务IP*/
    @Value("${calorie.rabbitmq.host:127.0.0.1}")
    private String host;

    /** 服务端口*/
    @Value("${calorie.rabbitmq.port:5672}")
    private int port;

    /** 用户名*/
    @Value("${calorie.rabbitmq.userName:guest}")
    private String userName;

    /** 用户密码*/
    @Value("${calorie.rabbitmq.password:guest}")
    private String password;

    /** Metrics报告周期*/
    @Value("${calorie.rabbitmq.metrics.report.interval:30}")
    private int reportInterval;

    /** 消息序列化的方式（1：jdk，2：json）*/
    @Value("${calorie.rabbitmq.serialize.type:2}")
    private int serializationType;

    /** 集群配置地址*/
    @Value("${calorie.rabbitmq.addresses:}")
    private String addresses;

    /** 虚拟主机*/
    @Value("${calorie.rabbitmq.vhost:/}")
    private String vhost;

    /** 最大Channel数*/
    @Value("${calorie.rabbitmq.maxChannels:25}")
    private int maxChannels;

    /** 连接超时时间，单位毫秒*/
    @Value("${calorie.rabbitmq.connectionTimeout:60000}")
    private int connectionTimeout;

    /** 心跳检查时间间隔，单位秒*/
    @Value("${calorie.rabbitmq.requestedHeartbeat:60}")
    private int requestedHeartbeat;

    /** 设置网络异常重连*/
    @Value("${calorie.rabbitmq.automaticRecoveryEnabled:false}")
    private boolean automaticRecoveryEnabled;

    /** 启用队列拓扑恢复*/
    @Value("${calorie.rabbitmq.topologyRecoveryEnabled:true}")
    private boolean topologyRecoveryEnabled;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Bean
    public ConnectionFactory rabbitConnectionFactory() {
    	CachingConnectionFactory cf = new CachingConnectionFactory();
        cf.setHost(host);
        cf.setPassword(password);
        cf.setUsername(userName);
        cf.setPort(port);
        cf.setVirtualHost(vhost);
        cf.setAddresses(addresses);
        cf.setChannelCacheSize(maxChannels);
        cf.getRabbitConnectionFactory().setTopologyRecoveryEnabled(topologyRecoveryEnabled);
        cf.getRabbitConnectionFactory().setAutomaticRecoveryEnabled(automaticRecoveryEnabled);
        cf.setConnectionTimeout(connectionTimeout);
        cf.setRequestedHeartBeat(requestedHeartbeat);
        return cf;
    }

    @Bean
    @ConditionalOnExpression("'${calorie.rabbitmq.enter:false}'=='true'")
    public RabbitTemplate rabbitTemplate(ConnectionFactory cf) {
        RabbitTemplate template = new RabbitTemplate(cf);
        return template;
    }

    @Bean
    @ConditionalOnExpression("'${calorie.rabbitmq.enter:false}'=='true'")
    public RabbitAdmin rabbitAdmin(ConnectionFactory cf) {
        RabbitAdmin admin = new RabbitAdmin(cf);
        return admin;
    }

    @Bean
    @ConditionalOnExpression("'${calorie.rabbitmq.enter:false}'=='true'")
    public RabbitMQService rabbitMQService(
            ConnectionFactory rabbitConnectionFactory,
            RabbitTemplate rabbitTemplate,
            RabbitAdmin admin) {
        RabbitMQService rabbitMQService = null;
        if (serializationType == 1) {
            rabbitMQService = new SimpleRabbitService(rabbitConnectionFactory, rabbitTemplate, admin);
        }else if (serializationType == 2){
            rabbitMQService = new SimpleRabbitService(rabbitConnectionFactory,rabbitTemplate,admin,new Jackson2JsonMessageConverter());
        }else{
            rabbitMQService = new SimpleRabbitService(rabbitConnectionFactory, rabbitTemplate, admin);
        }
        this.rabbitMQService = rabbitMQService;

        return  rabbitMQService;
    }

    @Bean
    public AutoConsumerBean autoConsumerBean() {
        // 配置自动化装载消费者
        if (autoListen) {
            Collection<RabbitMessageListener> rabbitListeners = applicationContext.getBeansOfType(RabbitMessageListener.class).values();
            Iterator<RabbitMessageListener> it = rabbitListeners.iterator();
            while (it.hasNext()) {
                RabbitMessageListener next = it.next();
                int concurrent = next.getConcurrent();
                if(concurrent > 1){
                    rabbitMQService.listen(next,concurrent);
                }else{
                    rabbitMQService.listen(next,1);
                }
            }
        }
        return new AutoConsumerBean();
    }

}
